package com.file.parser;

import com.file.bo.ResponseData;
import com.file.bo.mail.CMB;
import com.file.bo.mail.CMBTran;
import com.file.constant.EfpConstants;
import com.file.constant.ErrorCode;
import com.file.parser.traprange.PDFTableExtractor;
import com.file.util.JsonUtils;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class CMBPdfParser extends BasePdfParser {

	public ResponseData<String> parseCMBPdfToJson(String filePath) {
		log.info("parseCMBPdfToJson started, filePath:{}", filePath);
		String json = null;

		try {
			CMB cmb = parseCMBPdf(filePath);
			json = JsonUtils.convertObjectToJson(cmb);
		} catch (Exception e) {
			log.error("[OnError]parseCMBPdfToJson failed, filePath:{}", filePath, e);
			return new ResponseData<String>(json, ErrorCode.FILE_PARSE_EXCEPTION.getCode(),
					ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
		}

		log.info("parseCMBPdfToJson completed, filePath:{}", filePath);
		return new ResponseData<String>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
	}

	private CMB parseCMBPdf(String filePath) {
		CMB cmb = parseCMBHeader(filePath);
		List<CMBTran> cmbTrans = parseCMBTrans(filePath);
		try {
			cmbTrans = parseConterparty(filePath, cmbTrans);
		} catch (Exception e) {
			log.warn("parseConterparty failed", e);
		}
		cmb.setCmbTrans(cmbTrans);
		// log.info("cmb statement = " + cmb);
		return cmb;
	}

	private CMB parseCMBHeader(String filePath) {
		CMB cmb = new CMB();
		String pdfHeaderText = parsePdfHeaderText(filePath);
		pdfHeaderText = pdfHeaderText.substring(0, pdfHeaderText.indexOf("Date Verification Code"));

		String transDetailPeriod = pdfHeaderText
				.substring(pdfHeaderText.indexOf("China Merchants Bank") + 20, pdfHeaderText.indexOf("户 名：")).trim();
		String name = pdfHeaderText.substring(pdfHeaderText.indexOf("户 名：") + 4, pdfHeaderText.indexOf("账号：")).trim();
		String accountNo = pdfHeaderText
				.substring(pdfHeaderText.indexOf("账号：") + 3, pdfHeaderText.indexOf("Name Account")).trim();
		String accountType = pdfHeaderText
				.substring(pdfHeaderText.indexOf("账户类型：") + 5, pdfHeaderText.indexOf("开 户 行：")).trim();
		String subBranch = pdfHeaderText
				.substring(pdfHeaderText.indexOf("开 户 行：") + 6, pdfHeaderText.indexOf("Account Type")).trim();
		String date = pdfHeaderText.substring(pdfHeaderText.indexOf("申请时间：") + 5, pdfHeaderText.indexOf("验 证 码："))
				.trim();
		String verificationCode = pdfHeaderText.substring(pdfHeaderText.indexOf("验 证 码：") + 6).trim();
		cmb.setTransDetailPeriod(transDetailPeriod);
		cmb.setName(name);
		cmb.setAccountNo(accountNo);
		cmb.setAccountType(accountType);
		cmb.setSubBranch(subBranch);
		cmb.setDate(date);
		cmb.setVerificationCode(verificationCode);

		return cmb;
	}

	private List<CMBTran> parseCMBTrans(String filePath) {
		List<CMBTran> cmbTrans = new ArrayList<>();

		String transText = parseTransToText(filePath);
		if (Strings.isNullOrEmpty(transText)) {
			return cmbTrans;
		}

		List<List<String>> tranFieldsList = parseTransTextToTranFieldsList(transText);

		StringBuilder dateSb = new StringBuilder();
		StringBuilder currencySb = new StringBuilder();
		StringBuilder transactionAmountSb = new StringBuilder();
		StringBuilder balanceSb = new StringBuilder();
		StringBuilder transactionTypeSb = new StringBuilder();
		StringBuilder conterPartySb = new StringBuilder();

		for (List<String> strings : tranFieldsList) {
			dateSb.append(strings.get(0));
			currencySb.append(strings.get(1));
			transactionAmountSb.append(strings.get(2));
			balanceSb.append(strings.get(3));
			transactionTypeSb.append(strings.get(4));
			conterPartySb.append(strings.get(5));

			boolean isEndOfNewTran = !Strings.isNullOrEmpty(strings.get(0));
			if (isEndOfNewTran) {
				CMBTran cmbTran = new CMBTran();
				cmbTran.setDate(dateSb.toString());
				cmbTran.setCurrency(currencySb.toString());
				cmbTran.setTransactionAmount(transactionAmountSb.toString());
				cmbTran.setBalance(balanceSb.toString());
				cmbTran.setTransactionType(transactionTypeSb.toString());
				cmbTran.setCounterParty(conterPartySb.toString());
				cmbTrans.add(cmbTran);

				dateSb = new StringBuilder();
				currencySb = new StringBuilder();
				transactionAmountSb = new StringBuilder();
				balanceSb = new StringBuilder();
				transactionTypeSb = new StringBuilder();
				conterPartySb = new StringBuilder();
			}
		}

		return cmbTrans;
	}

	private String parseTransToText(String filePath) {
		PDFTableExtractor extractor = (new PDFTableExtractor()).setSource(filePath);
		int pdfPageNumber = getPdfPageNumber(filePath);
		// 去掉第一页的Header，
		int[] skipFirstPageHeaderLinesIndexes = new int[EfpConstants.CMB_PDF_HEADER_LINE_NUMBER];
		for (int i = 0; i < EfpConstants.CMB_PDF_HEADER_LINE_NUMBER; i++) {
			skipFirstPageHeaderLinesIndexes[i] = i;
		}
		extractor.exceptLine(0, skipFirstPageHeaderLinesIndexes);

		// 处理从第二页到最后一页的header
		for (int i = 1; i < pdfPageNumber; i++) {
			int[] skipLinesInNoneFirstPage = { 0, 1 };
			extractor.exceptLine(i, skipLinesInNoneFirstPage);
		}

		// 去掉最后一页的Footer,两种情况
		int lineNumberInLastPdf = getLineNumberInLastPage(filePath, pdfPageNumber);
		// 1.footer文本行完整展现在最后一页PDF,则直接排除最后一页的footer文本行
		if (lineNumberInLastPdf >= EfpConstants.CMB_PDF_FOOTER_LINE_NUMBER) {
			int[] skipLastPageFooterLinesIndexes = new int[EfpConstants.CMB_PDF_FOOTER_LINE_NUMBER];
			for (int j = 0; j < EfpConstants.CMB_PDF_FOOTER_LINE_NUMBER; j++) {
				skipLastPageFooterLinesIndexes[j] = -(j + 1);
			}
			extractor.exceptLine(pdfPageNumber - 1, skipLastPageFooterLinesIndexes);
		} else {
			// 2.footer文本行拆分在倒数第一页和倒数第二页，则直接排除最后一页和倒数第二页的WECHAT_FOOTER_LINE_NO-lineNumberInLastPdf
			extractor.exceptPage(pdfPageNumber - 1);

			int footerLinesNumberInlastSecondPage = EfpConstants.CMB_PDF_FOOTER_LINE_NUMBER - lineNumberInLastPdf;
			int[] skipLastSecondPageFooterLinesIndexes = new int[footerLinesNumberInlastSecondPage];
			for (int k = 0; k < footerLinesNumberInlastSecondPage; k++) {
				skipLastSecondPageFooterLinesIndexes[k] = -(k + 1);
			}
			extractor.exceptLine(pdfPageNumber - 2, skipLastSecondPageFooterLinesIndexes);
		}

		String text = extractPdfToText(extractor);
		return text;
	}

	public List<CMBTran> parseConterparty(String filePath, List<CMBTran> cmbTrans) {
		String pdfText = getPdfTextByStripper(filePath);
		pdfText = pdfText.replace(System.getProperty("line.separator", "\n"), " ");

		// 此处一行的格式2020-09-21 人民币 0.00 1.77 账户结息 应付利息-应付个人活期存款利息(自动计提)（新)
		// 973157320611009110
//		Pattern pattern1 = Pattern.compile("\\d{4}-\\d{2}-\\d{2}\\s\\S{1,10}\\s-?\\d{1,9}.\\d{2}\\s\\d{1,9}.\\d{2}\\s\\S{1,20}(\\s\\S{1,20}){1,3}\\s\\d{1,20}\\s");
		Pattern pattern1 = Pattern
				.compile("\\d{4}-\\d{2}-\\d{2}\\s\\S{1,10}\\s-?\\d{1,9}.\\d{2}\\s\\d{1,9}.\\d{2}\\s\\S{1,20}\\s");
		Matcher matcher1 = pattern1.matcher(pdfText);

		// 每行交易记录的第一个字所在的index
		int tranIndex = 0;
		Map<Integer, Integer> tranTextStartIndexMap = new HashMap<>();

		while (matcher1.find()) {
//			log.info(
//			"Match \"" + matcher1.group() + "\" at positions " + matcher1.start() + "-" + (matcher1.end() - 1));
			tranTextStartIndexMap.put(tranIndex, matcher1.start());
			tranIndex++;
		}

		// 找出每行交易记录的文本
		List<String> tranTextList = new ArrayList<>();
		for (int i = 1; i < tranTextStartIndexMap.size(); i++) {
			String tranText = pdfText.substring(tranTextStartIndexMap.get(i - 1), tranTextStartIndexMap.get(i));
			if (tranText.contains("记账日期")) {
				tranText = tranText.substring(0, tranText.indexOf("/") - 2).trim();
			}
			if (tranText.contains("—————")) {
				tranText = tranText.substring(0, tranText.indexOf("—————")).trim();
			}
			tranTextList.add(tranText);
		}

		String lastTranText = pdfText.substring(tranTextStartIndexMap.get(tranTextStartIndexMap.size() - 1));
		tranTextList.add(lastTranText);

		// 找出每行交易里的对手信息的值
		// 此处一行除去对手信息的格式2020-09-21 人民币 0.00 1.77 账户结息
		Pattern pattern2 = Pattern
				.compile("\\d{4}-\\d{2}-\\d{2}\\s\\S{1,10}\\s-?\\d{1,9}.\\d{2}\\s\\d{1,9}.\\d{2}\\s\\S{1,20}");
		for (int i = 0; i < cmbTrans.size(); i++) {
			Matcher matcher2 = pattern2.matcher(tranTextList.get(i));
			while (matcher2.find()) {
				String counterParty = tranTextList.get(i).substring(matcher2.end()).trim();
				cmbTrans.get(i).setCounterParty(counterParty.replace(" ", ""));
			}
		}

		return cmbTrans;
	}

	public static void main(String[] args) {
		CMBPdfParser cmbPdfParser = new CMBPdfParser();
		CMB cmb = cmbPdfParser.parseCMBPdf("E:\\data\\files\\CMB\\招商银行（含对手信息和完整卡号）.pdf");
//        CMB cmb = cmbPdfParser.parseCMBPdf("E:\\data\\files\\CMB\\20210923223538.pdf");
		String json = JsonUtils.convertObjectToJson(cmb);
		log.info(json);
	}

}
